/*
 * winstar.c
 *
 *  Created on: 17.03.2012
 *      Author: md5sum@alexsp.ru
 */

#include "winstar.h"
#include <util/delay.h>

typedef enum{READY=0,BUSY} _lcd_busy_t;
typedef enum{COMMAND=0,DATA} _lcd_dc_t;
typedef enum{WRITE=0,READ} _lcd_rw_t;


static inline void LCDdh(uint8_t a) {
	LCDport&=~(LCDdata_mask);LCDport|=(a) & LCDdata_mask;
}
static inline void LCDdl(uint8_t a) {
	LCDport&=~(LCDdata_mask);LCDport|=(a<<4) & LCDdata_mask;
}

static _lcd_busy_t LCD_pulse() {
	_lcd_busy_t tmp=READY;
	_delay_us(1);
	LCDport|=(1<<LCDe);
	_delay_us(1);
	if (LCDpin & LCDbusy_mask) tmp=BUSY;
	LCDport&=~(1<<LCDe);
	return tmp;
}

static _lcd_busy_t LCD_xmit(const uint8_t data, _lcd_dc_t dc, _lcd_rw_t rw) {
	uint8_t tmp;
	_lcd_busy_t busy;

	tmp=LCDport&(~(LCDdata_mask|(1<<LCDrs)|(1<<LCDrw)|(1<<LCDe)));
	if (rw) {
		LCDddr&=~(LCDdata_mask);tmp|=(1<<LCDrw);
	}else {
		LCDddr|=(LCDdata_mask);
	}
	if (dc) tmp|=(1<<LCDrs);
	LCDport=tmp;
	LCDdh(data);
	busy=LCD_pulse();
	LCDport=tmp;
	LCDdl(data);
	LCD_pulse();
	return busy;
}

#define LCD_busy() LCD_xmit(0xff,COMMAND,READ)

static void LCD_send_data(uint8_t command,_lcd_dc_t type) {
	while (LCD_busy()) _delay_us(1);
	LCD_xmit(command,type,WRITE);
}

void LCD_init() {
	LCDport=(LCDport&~(LCDdata_mask|(1<<LCDrs)|(1<<LCDrw)|(1<<LCDe)));
	LCDddr|=(LCDdata_mask|(1<<LCDrs)|(1<<LCDrw)|(1<<LCDe));
	_delay_ms(15);
	LCDdh(0x30);
	LCD_pulse();
	_delay_ms(5);
	//	LCDdh(0x30);
	LCD_pulse();
	_delay_us(150);
	//	LCDdh(0x30);
	LCD_pulse();
	_delay_us(50);
	LCDdh(0x20);
	LCD_pulse();

	LCD_send_data(0x28,COMMAND);
	LCD_send_data(0x08,COMMAND);
	LCD_send_data(0x01,COMMAND);
	LCD_send_data(0x02,COMMAND);
	LCD_send_data(0x06,COMMAND);
	//	LCD_send_data(0x0f,COMMAND); /*С курсором*/
	LCD_send_data(0x0c,COMMAND); /*Без курсора*/

	/*Загрузим доп символы*/
	/*значек градуса 0x08*/
	LCD_send_data(0x40,COMMAND);
	LCD_send_data(0x06,DATA);
	LCD_send_data(0x09,DATA);
	LCD_send_data(0x09,DATA);
	LCD_send_data(0x06,DATA);
	LCD_send_data(0x00,DATA);
	LCD_send_data(0x00,DATA);
	LCD_send_data(0x00,DATA);
	LCD_send_data(0x00,DATA);

	/*стрелочка 0x01*/
//	LCD_send_data(0x48,COMMAND);
	LCD_send_data(0x00,DATA);
	LCD_send_data(0x08,DATA);
	LCD_send_data(0x0c,DATA);
	LCD_send_data(0x1e,DATA);
	LCD_send_data(0x0c,DATA);
	LCD_send_data(0x08,DATA);
	LCD_send_data(0x00,DATA);
	LCD_send_data(0x00,DATA);

	/*указатели редактируемой переменной 0x02 0x03*/
	LCD_send_data(0x08,DATA);
	LCD_send_data(0x0c,DATA);
	LCD_send_data(0x0e,DATA);
	LCD_send_data(0x0f,DATA);
	LCD_send_data(0x0e,DATA);
	LCD_send_data(0x0c,DATA);
	LCD_send_data(0x08,DATA);
	LCD_send_data(0x00,DATA);

	LCD_send_data(0x02,DATA);
	LCD_send_data(0x06,DATA);
	LCD_send_data(0x0e,DATA);
	LCD_send_data(0x1e,DATA);
	LCD_send_data(0x0e,DATA);
	LCD_send_data(0x06,DATA);
	LCD_send_data(0x02,DATA);
	LCD_send_data(0x00,DATA);

}

/*
void LCD_prn(const char *str) {
	uint8_t *p;
	p=(uint8_t *)str;
	while (*p!=0) {
		LCD_send_data(*p,DATA);
		p++;
	}
}
void LCD_prn_p(const prog_char *str) {
	void *p;
	char a;
	p=(void *)str;
	while ((a=pgm_read_byte(p++))!=0) {
		LCD_send_data(a,DATA);
	}
}
*/

void LCD_char(uint8_t c) {
	LCD_send_data(c,DATA);
}

void LCD_xy(uint8_t col, uint8_t row) {
	uint8_t tmp;
	tmp=col|0x80;
	if (row) tmp|=0x40;
	LCD_send_data(tmp,COMMAND);
}

void LCD_clear() {
	LCD_send_data(0x01,COMMAND);
}

